Skip to content

fix(worktree): survive the renderer-era bmad-dev-auto (BMAD-METHOD #2587/#2588)#155

Open
pbean wants to merge 1 commit into
mainfrom
fix/renderer-era-dev-auto
Open

fix(worktree): survive the renderer-era bmad-dev-auto (BMAD-METHOD #2587/#2588)#155
pbean wants to merge 1 commit into
mainfrom
fix/renderer-era-dev-auto

Conversation

@pbean

@pbean pbean commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

What upstream changed

BMAD-METHOD 64157d39 (#2587) made bmad-dev-auto's SKILL.md a two-line shim — uv run {skill-root}/render.py, follow its stdout; on ANY failure "report what it printed and HALT". The old SKILL.md body moved to workflow.md, rendered into {project-root}/_bmad/render/bmad-dev-auto/ with config values and absolute paths baked in at render time. render.py finds {project-root} by walking UP from the session cwd to the first _bmad/ directory and requires the post-#2285 central _bmad/config.toml. Follow-up 1cd4a7f5 (#2588, upstream HEAD) hardened it: a {{.var}} referenced by the templates but missing from the merged config, or a present-but-unparseable customization layer, now hard-HALTs.

The completion contract bmad-loop parses is unchanged (verified against the diff): ## Auto Run Result, Status: line, frontmatter statuses, baseline_revision, the bmad-dev-auto-result- fallback prefix, folder+id dispatch, and the "folder+id dispatch" stories-probe literal all survive; every preflight marker file still exists. devcontract.py is untouched. The breakage is environmental, in two critical shapes:

  1. Walk-up contamination. Worktrees nest at <project>/.bmad-loop/runs/<id>/worktrees/… and never carried a _bmad/ (default worktree_seed = []), so render.py silently adopted the main checkout's _bmad/: rendered workflows baked main-checkout absolute artifact paths (deferred-work appends, no-spec fallback artifacts, and step-01 context all escaped the worktree — fallback artifacts landing where _artifact_dirs never looks), and every parallel session raced on one shared render dir that render.py delete-rewrites per invocation.
  2. HALT before the contract exists. The shim HALTs before workflow.md's HALT protocol is ever loaded, so a broken environment (no uv, no _bmad/config.toml, missing render.py, or a #2588 config HALT) writes no spec status at all — every story becomes a result-less Stop (the cascade fix(adapters): bound dev/review stall nudges + diagnose result-less Stops #151's breadcrumbs diagnose, one story at a time).

What this PR does

  • _bmad merge-seed in provision_worktree: per-FILE copy-when-absent of the main repo's _bmad/ into the worktree (a committed _bmad/ keeps every tracked file; the gitignored *.user.toml layers — whose absence hard-HALTs render.py since #2588 — are filled in), never seeding the regenerated render/. Shield rels follow the existing "shield exactly what we wrote" doctrine: one anchored /_bmad when the checkout had none, per-file rels when merging.
  • /_bmad/render/ always excluded (git-common-dir info/exclude), so session-rendered output (machine-absolute paths baked in) can't be swept into story commits by the unit's git add -A; bmad-loop init also gitignores _bmad/render/ for in-place (isolation = "none") runs.
  • Renderer preflight (install.missing_renderer_support) in validate and at run/sweep/resume start: render.py next to the shim, uv on PATH, _bmad/config.toml present. Gated on the installed SKILL.md actually containing render.py — pre-render installs get zero new checks and byte-stable validate output.
  • validate --render-probe (opt-in): executes the real uv run render.py against the project; pass = the read and follow … dispatch line. Surfaces #2588 render-time HALTs before a run. Side effect documented in --help (rewrites the regenerated _bmad/render/bmad-dev-auto/ cache).
  • Two validate warnings (never FAILs): four-layer-TOML vs legacy bmm/config.yaml desync on implementation_artifacts (bmadconfig.toml_artifact_parity, mirroring render.py's exact merge precedence — deep-merge layers, then [modules.bmm] beats [core]; TOML-first migration tracked in bmadconfig: read the four-layer central TOML as primary, legacy bmm/config.yaml as fallback #154), and a one-time "you have _bmad/render/** committed — git rm -r --cached it" hint (excludes can't shield tracked files).
  • Profiles confirmed unchanged: claude's native slash invocation and copilot's "LOAD the FULL SKILL.md … follow its directions exactly" both work against the two-line shim; the only failure mode (no uv in-session) is the preflight's job.

Verification

  • Full suite 2295 passed (+23 new tests), trunk check clean. New coverage: seed/merge/shield/symlink-escape, renderer-support matrix (incl. uv-missing reported once across trees), probe pass/HALT via a fake-uv launcher (no test executes real uv — Windows CI safe), an end-to-end engine test proving a committed-_bmad project's worktree gets the gitignored user layer seeded and the session's render residue never reaches the story commit, and TOML-parity precedence tests.
  • Real smoke on this repo with the actual upstream skill resynced to 1cd4a7f5: validate detects the shim and passes the preflight; validate --render-probe ran the real renderer via uv and produced its dispatch line; the rendered step-04 confirms the absolute-path baking the seed protects against.

Follow-ups

Summary by CodeRabbit

  • New Features

    • Added renderer-era preflight checks for render.py, uv, and centralized configuration.
    • Added validate --render-probe to detect render-time failures and configuration issues.
    • Improved isolated worktree setup by seeding required configuration while excluding generated render output.
  • Bug Fixes

    • Prevented renderer artifacts and user configuration layers from being included in commits.
    • Added warnings for configuration mismatches and already-tracked render output.
  • Documentation

    • Updated setup, feature, contribution, and changelog documentation with renderer validation and worktree behavior.

…587/#2588)

Upstream bmad-dev-auto's SKILL.md is now a two-line shim that runs
`uv run render.py` and follows its stdout; the renderer anchors its
project root on the first _bmad/ dir walking UP from the session cwd,
requires the post-#2285 _bmad/config.toml, and rewrites
_bmad/render/bmad-dev-auto/ with absolute paths baked in. The completion
contract bmad-loop parses is unchanged — the breakage is environmental:

- Worktrees nest under <project>/.bmad-loop/runs/ and never carried a
  _bmad/, so render.py silently adopted the MAIN checkout's: rendered
  workflows baked main-checkout absolute artifact paths (deferred-work
  appends, no-spec fallback artifacts, and step-01 context escaped the
  worktree — fallbacks landing where _artifact_dirs never looks) and
  every parallel session raced on one shared, delete-rewritten render
  dir. provision_worktree now merge-seeds the main repo's _bmad/ config
  surface per-file (copy-when-absent: a committed _bmad/ keeps every
  tracked file; the gitignored *.user.toml layers — whose absence
  hard-HALTs render.py since #2588 — are filled in), never seeds the
  regenerated render/, and shields it: one anchored /_bmad exclude when
  the checkout had none, per-file rels when merging into an existing
  tree.

- /_bmad/render/ is always excluded (seeded or not) so session-rendered
  output can't be swept into story commits by the unit's `git add -A`;
  `bmad-loop init` also gitignores _bmad/render/ for in-place runs.

- The shim HALTs on any failure BEFORE the workflow's HALT protocol is
  loaded, so a broken environment (no uv, no central config, missing
  render.py) yields one result-less Stop per story with no spec status
  ever written. A renderer preflight (validate + run/sweep/resume start)
  now fails loudly instead — gated on the installed SKILL.md actually
  being the render shim, so pre-render installs see zero new checks and
  byte-stable validate output.

- `validate --render-probe` (opt-in) executes the real renderer against
  the project to surface render-time HALTs (#2588: missing {{.var}}
  keys, unparseable override layers) before a run burns a story.

- validate warns (never fails) when the four-layer central TOML and the
  legacy _bmad/bmm/config.yaml disagree on implementation_artifacts
  (the renderer follows the TOML, the orchestrator reads the yaml —
  TOML-first migration tracked in #154), and once when a project has
  already committed _bmad/render/** (excludes can't shield tracked
  files; `git rm -r --cached` remediation printed).
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7717357a-15ec-4bab-93de-7b0479f3626d

📥 Commits

Reviewing files that changed from the base of the PR and between cef401b and db08a5c.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • CONTRIBUTING.md
  • docs/FEATURES.md
  • docs/setup-guide.md
  • src/bmad_loop/bmadconfig.py
  • src/bmad_loop/cli.py
  • src/bmad_loop/install.py
  • tests/test_bmadconfig.py
  • tests/test_cli.py
  • tests/test_engine_worktree.py
  • tests/test_install.py

Walkthrough

Renderer-era preflight, render probing, TOML artifact parity warnings, and worktree _bmad/ seeding with generated-render shielding are implemented, tested, and documented.

Changes

Renderer validation and artifact parity

Layer / File(s) Summary
Renderer validation and artifact parity
src/bmad_loop/{bmadconfig,cli,install}.py, tests/test_{bmadconfig,cli}.py, docs/*, CHANGELOG.md, CONTRIBUTING.md
Validation checks renderer prerequisites, optionally runs render.py through uv, reports HALTs, and warns about TOML/YAML artifact-path mismatches.

Worktree configuration seeding and render shielding

Layer / File(s) Summary
Worktree configuration seeding and render shielding
src/bmad_loop/install.py, tests/test_install.py, tests/test_engine_worktree.py, docs/FEATURES.md, CHANGELOG.md
Worktrees merge-seed missing _bmad/ configuration, reject escaping symlinks, and exclude _bmad/render/ and seeded files from commits.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Validator as bmad-loop validate
  participant Support as missing_renderer_support
  participant UV as uv
  participant Renderer as render.py
  Validator->>Support: check render.py, uv, and _bmad/config.toml
  Validator->>UV: execute uv run render.py
  UV->>Renderer: start renderer probe
  Renderer-->>Validator: dispatch output or HALT details
Loading

Possibly related issues

  • Issue 154 — Adds TOML artifact parity between central TOML resolution and legacy bmm/config.yaml.

Suggested reviewers: dracic

Poem

A rabbit checks the render gate,
With TOML paths aligned in state.
Worktrees sprout configs, neat and bright,
While render crumbs stay out of sight.
Hop, hop—validation’s green tonight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.81% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: worktree isolation and preflight updates for renderer-era bmad-dev-auto.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/renderer-era-dev-auto

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant